﻿using PropertyExpression.CalcExpression;

namespace PropertyExpression.CalcExpression.Test
{
    public partial class Aaa : ICalcEntity
    {
        partial void OnLoaded()
        {
            AddCalc();
        }

        public NewPropertyHolder<Aaa, decimal> A001Holder
        {
            get { return a001Holder; }
        }

        private NewPropertyHolder<Aaa, decimal> a001Holder;

        public EntitySetWrapper<Bbb> BbbsWrapper { get; private set; }

        public EntitySetWrapper<Ccc> CccsWrapper { get; private set; }

        partial void OnCreated()
        {
            BbbsWrapper = new EntitySetWrapper<Bbb>(Bbbs);

            CccsWrapper = new EntitySetWrapper<Ccc>(Cccs);

            a001Holder = this.NewPropertyHolder(
                x => x.A001,
                delegate
                    {
                        Bbbs.GetEnumerator().MoveNext();
                    });

        }

        public void AddCalc()
        {
            var calcBinder = new CalcBinder();

            calcBinder.Bind(
                x => A002 = x,
                BbbsWrapper.Sum(
                    entity => entity.Val(x => x.B001).Add(entity.Val(x => x.B002))
                    )
                );

            calcBinder.Bind(
                x => A003 = x,
                this.Val(x => x.A001).Add(this.Val(x => x.A002))
                );

            calcBinder.Bind(
                x => A006 = x,
                this.Val(x => x.A004).Func(this.Val(x => x.A005), (date, days) => date.AddDays(days))
                );


            calcBinder.BeginCalc();
        }
    }

    public partial class Bbb : ICalcEntity
    {
        partial void OnLoaded()
        {
            AddCalc();
        }

        partial void OnCreated()
        {
            new EntityRefWrapper<Bbb, Aaa>(this, x => x.Aaa, x => x.BbbsWrapper);
        }

        //QQDO: подумать над началом вычислений

        public void AddCalc()
        {
            var calcBinder = new CalcBinder();

            calcBinder.Bind(
                x => B002 = x,
                this.Val(x => x.B001).Mult(this.Val(x => x.Aaa).Val(x => x.A001))
                );

            calcBinder.Bind(
                x => B003 = x,
                this.Val(x => x.B002).Func(x => x * 5)
                );

            calcBinder.Bind(
                x => B004 = x,
                this.Val(x => x.Aaa).ValueFunc(
                              aaa => aaa.CccsWrapper.Sum(ccc => ccc.Val(x => x.C001)))
                );

            calcBinder.BeginCalc();
        }
    }

    public partial class Ccc : ICalcEntity
    {
        partial void OnLoaded()
        {
            AddCalc();
        }

        partial void OnCreated()
        {
            new EntityRefWrapper<Ccc, Aaa>(this, x => x.Aaa, x => x.CccsWrapper);
        }

        public void AddCalc()
        {
            //no-op
        }
    }

    public partial class EntityA
    {
        private NewPropertyHolder<EntityA, decimal> totalSumHolder;
        public EntitySetWrapper<EntityB> EntityBsWrapper { get; private set; }

        partial void OnCreated()
        {
            EntityBsWrapper = new EntitySetWrapper<EntityB>(EntityBs);

            totalSumHolder = this.NewPropertyHolder(
                x => x.TotalSum,
                delegate
                    {
                        EntityBs.GetEnumerator().MoveNext();
                    });
        }

        public NewPropertyHolder<EntityA, decimal> TotalSumHolder
        {
            get
            {
                return totalSumHolder;
            }
        }
    }

}
